Purge stale public.wsg_outlet references; document the ltree-closure trap - #243
Merged
Conversation
…trap #227/v0.45.1 removed public.wsg_outlet as a concept, but references survived in places that still steer behaviour: - R/lnk_log.R listed public.wsg_outlet as a pipeline input primitive, so the run-provenance log (v0.45.0) fingerprints a table that should not exist. On a machine with the leftover table it records real numbers for a phantom dependency; on a clean one it records NULLs for a table that was never a dependency. Removed. - research/study_areas.md documented the *superseded* technique as current -- "closure and downstream-first order are derived from wscode_ltree ancestry (@>)" -- and pointed at #227 as the issue tracking its reproducible build, when #227 was re-scoped to delete it. Rewritten to point at lnk_wsg_resolve() with an explicit do-not. - research/study_area_run.md and data-raw/study_area_run.sh referenced the table in prose. Repointed. data-raw/study_area_wsgs.R was already a shim around lnk_wsg_resolve(), so no live code path was wrong. Adds RUNBOOK section 8b, which did not previously warn about any of this. The trap is that two watershed groups on the same stream share an outlet code, so `a.outlet @> b.outlet` is true in both directions and reports each as downstream of the other. Worked example is the Kootenay, where FWA carries the out-and-back through Montana and Idaho under one continuous wscode -- an ltree test puts KOTR/SMAR/BULL below Kootenay Lake when they are above it via the US, and the true closure of LARL/KOTL/SLOC is just those three. Found by falling into it: a hand-rolled @> query produced a five-WSG "outstanding downstream closure" that does not exist.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
public.wsg_outletwas removed as a concept by #227/v0.45.1 (fresh 0.33.0 ships outlets and passes them as aVALUESlist). References survived in places that still steer behaviour — including one in code I shipped in v0.45.0.What was wrong
R/lnk_log.Rpublic.wsg_outletas a pipeline input primitive, so the run-provenance log fingerprints a table that should not exist — real numbers for a phantom dependency on a machine with the leftover table, NULLs on a clean oneresearch/study_areas.mdwscode_ltreeancestry (@>)" — and cited #227 as tracking the table's "reproducible build", when #227 was re-scoped to delete itresearch/study_area_run.md,data-raw/study_area_run.shdata-raw/study_area_wsgs.Rwas already a shim aroundlnk_wsg_resolve(), so no live code path computed a wrong closure. The damage was documentation steering a reader into the trap.The trap, now in RUNBOOK §8b
Two watershed groups on the same stream share an outlet code, so
a.outlet @> b.outletis true in both directions and reports each as downstream of the other. Closure is measure-aware, not code-aware — which is whyc("PARS","BULK")dropped from 15 WSGs to 9 when #238 adopted fresh 0.33.0.The worked example is the Kootenay, where it bites hardest. FWA carries the whole river under one continuous
wscode_ltree = 300.625474, including the stretch that leaves BC near Newgate, runs through Montana and Idaho, and re-enters at Creston. Measures chain with no gap:So KOTR/SMAR/BULL are upstream of Kootenay Lake via the US loop — but an ltree test sees them sharing KOTL's outlet code and calls them downstream. The correct closure of
c("LARL","KOTL","SLOC")is just those three: LARL is the terminal BC group (it holds the Kootenay's mouth at Castlegar and the Columbia down to the border — hence Waneta and Seven Mile sitting in it), and below it is the United States.§8b also records that a
public.wsg_outlettable found in any database is a leftover: it still answers queries, and answers them wrongly.How it was found
By falling into it. A hand-rolled
@>closure query produced a five-WSG "outstanding downstream closure" (KOTR, COLR, BULL, SMAR, UARL) that does not exist — caught when the geography was questioned, and confirmed bylnk_wsg_resolve()returning exactly the three groups already modelled.Verification
devtools::test()ontest-lnk_log.R— 128 pass. No behavioural change beyond dropping the phantom primitive fromlog_input.🤖 Generated with Claude Code
https://claude.ai/code/session_014kSEJoad4Bc553qU8eFiE6